home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / nthsurfdemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  12.4 KB  |  591 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <GL/glut.h>
  5.  
  6. /* Some <math.h> files do not define M_PI... */
  7. #ifndef M_PI
  8. #define M_PI 3.14159265358979323846
  9. #endif
  10.  
  11. #define TRUE    1
  12. #define FALSE    0
  13.  
  14. int whichSurface = 0;
  15. int takeSnapshot = 0;
  16.  
  17.  
  18. int         winWidth, winHeight;
  19. GLfloat     *depthSave = NULL;
  20. GLubyte     *stencilSave = NULL;
  21. GLubyte     *colorSave = NULL;
  22.  
  23.  
  24. void resizeBuffers(void)
  25. {
  26.     colorSave = realloc(colorSave, winWidth * winHeight * 4 * sizeof(GLubyte));
  27.     depthSave = realloc(depthSave, winWidth * winHeight * 4 * sizeof(GLfloat));
  28.     stencilSave = (GLubyte *)depthSave;
  29. }
  30.  
  31.  
  32. void pushOrthoView(float left, float right, float bottom, float top,
  33.     float znear, float zfar)
  34. {
  35.     glPushMatrix();
  36.     glLoadIdentity();
  37.     glMatrixMode(GL_PROJECTION);
  38.     glPushMatrix();
  39.     glLoadIdentity();
  40.     glOrtho(left, right, bottom, top, znear, zfar);
  41. }
  42.  
  43.  
  44. void popView(void)
  45. {
  46.     glPopMatrix();
  47.     glMatrixMode(GL_MODELVIEW);
  48.     glPopMatrix();
  49. }
  50.  
  51.  
  52. void copyDepthToColor(GLenum whichColorBuffer)
  53. {
  54.     int        x, y;
  55.     GLfloat    max, min;
  56.     GLint    previousColorBuffer;
  57.  
  58.     glReadPixels(0, 0, winWidth, winHeight, GL_DEPTH_COMPONENT, GL_FLOAT,
  59.         depthSave);
  60.  
  61.     /* I'm sure this could be done much better with OpenGL */
  62.     max = 0;
  63.     min = 1;
  64.     for(y = 0; y < winHeight; y++)
  65.     for(x = 0; x < winWidth; x++) {
  66.         if(depthSave[winWidth * y + x] < min)
  67.         min = depthSave[winWidth * y + x];
  68.         if(depthSave[winWidth * y + x] > max && depthSave[winWidth * y + x] < .999)
  69.         max = depthSave[winWidth * y + x];
  70.     }
  71.  
  72.     for(y = 0; y < winHeight; y++)
  73.     for(x = 0; x < winWidth; x++) {
  74.         if(depthSave[winWidth * y + x] <= max)
  75.         depthSave[winWidth * y + x] = 1 -  (depthSave[winWidth * y + x] - min) / (max - min);
  76.         else
  77.         depthSave[winWidth * y + x] = 0;
  78.     }
  79.  
  80.     pushOrthoView(0, 1, 0, 1, 0, 1);
  81.     glRasterPos3f(0, 0, -.5);
  82.     glDisable(GL_DEPTH_TEST);
  83.     glDisable(GL_STENCIL_TEST);
  84.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  85.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  86.     glDrawBuffer(whichColorBuffer);
  87.     glDrawPixels(winWidth, winHeight, GL_LUMINANCE , GL_FLOAT, depthSave);
  88.     glDrawBuffer(previousColorBuffer);
  89.     glEnable(GL_DEPTH_TEST);
  90.     popView();
  91. }
  92.  
  93.  
  94. unsigned char colors[][3] =
  95. {
  96.     {255, 0, 0},    /* red */
  97.     {255, 218, 0},    /* yellow */
  98.     {72, 255, 0},    /* yellowish green */
  99.     {0, 255, 145},    /* bluish cyan */
  100.     {0, 145, 255},    /* cyanish blue */
  101.     {72, 0, 255},    /* purplish blue */
  102.     {255, 0, 218},    /* reddish purple */
  103. };
  104.  
  105.  
  106. void copyStencilToColor(GLenum whichColorBuffer)
  107. {
  108.     int        x, y;
  109.     GLint    previousColorBuffer;
  110.  
  111.     glReadPixels(0, 0, winWidth, winHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
  112.         stencilSave);
  113.  
  114.     /* I'm sure this could be done much better with OpenGL */
  115.     for(y = 0; y < winHeight; y++)
  116.     for(x = 0; x < winWidth; x++) {
  117.         int stencilValue;
  118.         
  119.         stencilValue = stencilSave[winWidth * y + x];
  120.  
  121.         colorSave[(winWidth * y + x) * 3 + 0] = colors[stencilValue % 7][0];
  122.         colorSave[(winWidth * y + x) * 3 + 1] = colors[stencilValue % 7][1];
  123.         colorSave[(winWidth * y + x) * 3 + 2] = colors[stencilValue % 7][2];
  124.     }
  125.  
  126.     pushOrthoView(0, 1, 0, 1, 0, 1);
  127.     glRasterPos3f(0, 0, -.5);
  128.     glDisable(GL_DEPTH_TEST);
  129.     glDisable(GL_STENCIL_TEST);
  130.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  131.     glGetIntegerv(GL_DRAW_BUFFER, &previousColorBuffer);
  132.     glDrawBuffer(whichColorBuffer);
  133.     glDrawPixels(winWidth, winHeight, GL_RGB, GL_UNSIGNED_BYTE, colorSave);
  134.     glDrawBuffer(previousColorBuffer);
  135.     glEnable(GL_DEPTH_TEST);
  136.     popView();
  137. }
  138.  
  139.  
  140. #if 0
  141.  
  142. GLushort rrow[1280], grow[1280], brow[1280], arow[1280];
  143.  
  144.  
  145. #define iopen junk
  146. #include <gl/image.h>
  147. #undef iopen
  148.  
  149.  
  150. IMAGE *iopen(char *file, char *mode, ...);
  151. int putrow(IMAGE *image, unsigned short *buff, int y, int z);
  152. int iclose(IMAGE *);
  153.  
  154.  
  155. void saveSGIImage(char *name, int doAlphaToo)
  156. {
  157.     IMAGE *img;
  158.     FILE *fp;
  159.     GLubyte *pixels; 
  160.     int x, y;
  161.     int numComp = doAlphaToo ? 4 : 3;
  162.  
  163.     pixels = malloc(winWidth * winHeight * numComp * sizeof(GLubyte));
  164.  
  165.     glReadPixels(0, 0, winWidth, winHeight, doAlphaToo ? GL_RGBA : GL_RGB,
  166.         GL_UNSIGNED_BYTE, pixels);
  167.  
  168.     img = iopen(name, "w", RLE(1), numComp, winWidth, winHeight, numComp);
  169.  
  170.     for(y = 0; y < winHeight; y++) {
  171.         for(x = 0; x < winWidth; x++) {
  172.         rrow[x] = pixels[(y * winWidth + x) * numComp + 0];
  173.         grow[x] = pixels[(y * winWidth + x) * numComp + 1];
  174.         brow[x] = pixels[(y * winWidth + x) * numComp + 2];
  175.         if(doAlphaToo)
  176.         arow[x] = pixels[(y * winWidth + x) * numComp + 3];
  177.     }
  178.         putrow(img, rrow, y, 0);
  179.         putrow(img, grow, y, 1);
  180.         putrow(img, brow, y, 2);
  181.     if(doAlphaToo)
  182.         putrow(img, arow, y, 3);
  183.     }
  184.     iclose(img);
  185.  
  186.     free(pixels);
  187. }
  188.  
  189. #endif
  190.  
  191.  
  192. struct transformation {
  193.     float    translation[3];
  194.     float    rotation[4];
  195.     float    scale[3];
  196. };
  197.  
  198.  
  199. void drawXform(struct transformation *xform, int applyScale)
  200. {
  201.     glTranslatef(xform->translation[0], xform->translation[1], xform->translation[2]);
  202.     glRotatef(xform->rotation[3] / M_PI * 180, xform->rotation[0], xform->rotation[1], xform->rotation[2]);
  203.     if(applyScale)
  204.     glScalef(xform->scale[0], xform->scale[1], xform->scale[2]);
  205. }
  206.  
  207.  
  208. enum trackballModeEnum {
  209.     ROTATE,
  210.     TRANSLATEXY,
  211.     TRANSLATEZ,
  212.     SCALEX,
  213.     SCALEY,
  214.     SCALEZ
  215. } trackballMode = ROTATE;
  216.  
  217.  
  218. struct transformation xform = 
  219. {
  220.     0, 0, 0,
  221.     -0.65, -0.75, -0.04, 0.89,
  222.     .7, .7, 2,
  223. };
  224.  
  225.  
  226. void axisamountToMat(float aa[], float mat[])
  227. {
  228.     float c, s, t;
  229.  
  230.     c = (float)cos(aa[3]);
  231.     s = (float)sin(aa[3]);
  232.     t = 1.0f - c;
  233.  
  234.     mat[0] = t * aa[0] * aa[0] + c;
  235.     mat[1] = t * aa[0] * aa[1] + s * aa[2];
  236.     mat[2] = t * aa[0] * aa[2] - s * aa[1];
  237.     mat[3] = t * aa[0] * aa[1] - s * aa[2];
  238.     mat[4] = t * aa[1] * aa[1] + c;
  239.     mat[5] = t * aa[1] * aa[2] + s * aa[0];
  240.     mat[6] = t * aa[0] * aa[2] + s * aa[1];
  241.     mat[7] = t * aa[1] * aa[2] - s * aa[0];
  242.     mat[8] = t * aa[2] * aa[2] + c;
  243. }
  244.  
  245.  
  246. void matToAxisamount(float mat[], float aa[])
  247. {
  248.     float c;
  249.     float s;
  250.  
  251.     c = (mat[0] + mat[4] + mat[8] - 1.0f) / 2.0f;
  252.     aa[3] = (float)acos(c);
  253.     s = (float)sin(aa[3]);
  254.     if(fabs(s / M_PI - (int)(s / M_PI)) < .0000001)
  255.     {
  256.         aa[0] = 0.0f;
  257.         aa[1] = 1.0f;
  258.         aa[2] = 0.0f;
  259.     }
  260.     else
  261.     {
  262.     aa[0] = (mat[5] - mat[7]) / (2.0f * s);
  263.     aa[1] = (mat[6] - mat[2]) / (2.0f * s);
  264.     aa[2] = (mat[1] - mat[3]) / (2.0f * s);
  265.     }
  266. }
  267.  
  268.  
  269. void multMat(float m1[], float m2[], float r[])
  270. {
  271.     float t[9];
  272.     int i;
  273.  
  274.     t[0] = m1[0] * m2[0] + m1[1] * m2[3] + m1[2] * m2[6];
  275.     t[1] = m1[0] * m2[1] + m1[1] * m2[4] + m1[2] * m2[7];
  276.     t[2] = m1[0] * m2[2] + m1[1] * m2[5] + m1[2] * m2[8];
  277.     t[3] = m1[3] * m2[0] + m1[4] * m2[3] + m1[5] * m2[6];
  278.     t[4] = m1[3] * m2[1] + m1[4] * m2[4] + m1[5] * m2[7];
  279.     t[5] = m1[3] * m2[2] + m1[4] * m2[5] + m1[5] * m2[8];
  280.     t[6] = m1[6] * m2[0] + m1[7] * m2[3] + m1[8] * m2[6];
  281.     t[7] = m1[6] * m2[1] + m1[7] * m2[4] + m1[8] * m2[7];
  282.     t[8] = m1[6] * m2[2] + m1[7] * m2[5] + m1[8] * m2[8];
  283.     for(i = 0; i < 9; i++)
  284.     {
  285.         r[i] = t[i];
  286.     }
  287. }
  288.  
  289.  
  290. void rotateTrackball(int dx, int dy, float rotation[4])
  291. {
  292.     float dist;
  293.     float oldMat[9];
  294.     float rotMat[9];
  295.     float newRot[4];
  296.  
  297.     dist = (float)sqrt((double)(dx * dx + dy * dy));
  298.     if(fabs(dist) < 0.99)
  299.         return;
  300.  
  301.     newRot[0] = (float) dy / dist;
  302.     newRot[1] = (float) dx / dist;
  303.     newRot[2] = 0.0f;
  304.     newRot[3] = (float)M_PI * dist / winWidth;
  305.  
  306.     axisamountToMat(rotation, oldMat);
  307.     axisamountToMat(newRot, rotMat);
  308.     multMat(oldMat, rotMat, oldMat);
  309.     matToAxisamount(oldMat, rotation);
  310.  
  311.     dist = (float)sqrt(rotation[0] * rotation[0] + rotation[1] * rotation[1] +
  312.         rotation[2] * rotation[2]);
  313.  
  314.     rotation[0] /= dist;
  315.     rotation[1] /= dist;
  316.     rotation[2] /= dist;
  317. }
  318.  
  319.  
  320. int stage = 6;
  321. typedef enum {COLOR, DEPTH, STENCIL} BufferInterest;
  322.  
  323. BufferInterest bufferInterest = COLOR;
  324.  
  325.  
  326. void init(void)
  327. {
  328.     GLfloat defaultMat[] = {.75, .25, .25, 1};
  329.  
  330.     glEnable(GL_DEPTH_TEST);
  331.     glEnable(GL_CULL_FACE);
  332.     glCullFace(GL_BACK);
  333.  
  334.     glMatrixMode(GL_PROJECTION);
  335.     glFrustum(-.33, .33, -.33, .33, .5, 40);
  336.  
  337.     glMatrixMode(GL_MODELVIEW);
  338.     gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
  339.  
  340.     glEnable(GL_LIGHTING);
  341.     glEnable(GL_LIGHT0);
  342.  
  343.     /* glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); */
  344.  
  345.     glEnable(GL_NORMALIZE);
  346.  
  347.     glEnable(GL_STENCIL_TEST);
  348.     glStencilOp(GL_INCR, GL_INCR, GL_INCR);
  349.  
  350.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, defaultMat);
  351.  
  352.     glLineWidth(3);
  353.     glShadeModel(GL_FLAT);
  354. }
  355.  
  356.  
  357. void redraw(void)
  358. {
  359.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
  360.     
  361.     glPushMatrix();
  362.  
  363.     drawXform(&xform, TRUE);
  364.  
  365.     glEnable(GL_STENCIL_TEST);
  366.     if(whichSurface < 2)
  367.     glStencilFunc(GL_EQUAL, whichSurface, 0xff);
  368.     else
  369.     glStencilFunc(GL_ALWAYS, 0, 0);
  370.  
  371.     glutSolidTorus(2, 4, 20, 20);
  372.  
  373.     /* glDisable(GL_STENCIL_TEST); */
  374.     /* glDisable(GL_LIGHTING); */
  375.     /* glColor3f(1, 1, 1); */
  376.     /* glutWireTorus(2, 4, 20, 20); */
  377.     /* glEnable(GL_LIGHTING); */
  378.  
  379.     glPopMatrix();
  380.  
  381.     switch(bufferInterest) {
  382.         case COLOR:
  383.         break; /* color already in back buffer */
  384.  
  385.     case STENCIL:
  386.         copyStencilToColor(GL_BACK);
  387.         break;
  388.  
  389.     case DEPTH:
  390.         copyDepthToColor(GL_BACK);
  391.         break;
  392.     }
  393.  
  394.     if(takeSnapshot) {
  395.         takeSnapshot = 0;
  396.     /* saveSGIImage("snap.rgb", FALSE); */
  397.     /* printf("Saved RGBA image in snap.rgba\n"); */
  398.     }
  399.  
  400.     glutSwapBuffers();
  401. }
  402.  
  403.  
  404. void reshape(int width, int height)
  405. {
  406.     glViewport(0, 0, width, height);
  407.     winWidth = width;
  408.     winHeight = height;
  409.     resizeBuffers();
  410.     glutPostRedisplay();
  411. }
  412.  
  413.  
  414. void changeData(int data)
  415. {
  416.     char *s;
  417.  
  418.     bufferInterest = (BufferInterest) data;
  419.     glutPostRedisplay();
  420.  
  421.     switch(data) {
  422.         case COLOR:
  423.         s = "color";
  424.         break;
  425.  
  426.         case STENCIL:
  427.         s = "stencil";
  428.         break;
  429.  
  430.         case DEPTH:
  431.         s = "depth";
  432.         break;
  433.     }
  434.     printf("Now displaying %s data\n", s);
  435. }
  436.  
  437.  
  438. int mainMenu;
  439.  
  440.  
  441. /* ARGSUSED1 */
  442. void keyboard(unsigned char key, int x, int y)
  443. {
  444.     switch(key)
  445.     {
  446.         case '1':
  447.         case '2':
  448.         case '3':
  449.         whichSurface = key - '1';
  450.         glutPostRedisplay();
  451.         break;
  452.  
  453.         case 'r':
  454.         trackballMode = ROTATE;
  455.         break;
  456.  
  457.     case 't':
  458.         trackballMode = TRANSLATEXY;
  459.         break;
  460.  
  461.     case 'T':
  462.         trackballMode = TRANSLATEZ;
  463.         break;
  464.  
  465.     case 'x':
  466.         trackballMode = SCALEX;
  467.         break;
  468.  
  469.     case 'y':
  470.         trackballMode = SCALEY;
  471.         break;
  472.  
  473.     case 'z':
  474.         trackballMode = SCALEZ;
  475.         break;
  476.  
  477.     case 'q': case 'Q': case '\033':
  478.         exit(0);
  479.         break;
  480.  
  481.     case '+': case '=':
  482.         stage++;
  483.         glutPostRedisplay();
  484.         break;
  485.  
  486.     case '-': case '_':
  487.         stage--;
  488.         glutPostRedisplay();
  489.         break;
  490.  
  491.     case 's':
  492.         printf("%f %f %f %f\n", xform.rotation[0], xform.rotation[1],
  493.             xform.rotation[2], xform.rotation[3]);
  494.         glutPostRedisplay();
  495.         break;
  496.     }
  497. }
  498.  
  499.  
  500. static int ox, oy;
  501.  
  502.  
  503. /* ARGSUSED */
  504. void button(int b, int state, int x, int y)
  505. {
  506.     ox = x;
  507.     oy = y;
  508. }
  509.  
  510.  
  511. void motion(int x, int y)
  512. {
  513.     int dx, dy;
  514.  
  515.     dx = x - ox;
  516.     dy = y - oy;
  517.  
  518.     ox = x;
  519.     oy = y;
  520.  
  521.     switch(trackballMode) {
  522.     case ROTATE:
  523.         rotateTrackball(dx, dy, xform.rotation);
  524.         break;
  525.  
  526.     case SCALEX:
  527.         xform.scale[0] += (dx + dy) / 20.0f;
  528.         break;
  529.  
  530.     case SCALEY:
  531.         xform.scale[1] += (dx + dy) / 20.0f;
  532.         break;
  533.  
  534.     case SCALEZ:
  535.         xform.scale[2] += (dx + dy) / 20.0f;
  536.         break;
  537.  
  538.     case TRANSLATEXY:
  539.         xform.translation[0] += dx / 20.0f;
  540.         xform.translation[1] -= dy / 20.0f;
  541.         break;
  542.  
  543.     case TRANSLATEZ:
  544.         xform.translation[2] += (dx + dy) / 20.0f;
  545.         break;
  546.     }
  547.     glutPostRedisplay();
  548. }
  549.  
  550. /* ARGSUSED */
  551. void mainMenuFunc(int menu)
  552. {
  553.     /* */
  554. }
  555.  
  556.  
  557. int main(int argc, char **argv)
  558. {
  559.     int bufferMenu;
  560.     int stenSize;
  561.  
  562.     glutInit(&argc, argv);
  563.     glutInitWindowSize(winWidth = 256, winHeight = 256);
  564.     glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH|GLUT_ALPHA);
  565.     (void)glutCreateWindow("torus depth");
  566.     glutDisplayFunc(redraw);
  567.     glutKeyboardFunc(keyboard);
  568.     glutMotionFunc(motion);
  569.     glutMouseFunc(button);
  570.     glutReshapeFunc(reshape);
  571.  
  572.     resizeBuffers();
  573.     glGetIntegerv(GL_STENCIL_BITS, &stenSize);
  574.     fprintf(stderr, "(%d bits of stencil available in this visual)\n", stenSize);
  575.  
  576.     fprintf(stderr, "Hit 'h' for help message\n");
  577.  
  578.     bufferMenu = glutCreateMenu(changeData);
  579.     glutAddMenuEntry("Color data", COLOR);
  580.     glutAddMenuEntry("Stencil data", STENCIL);
  581.     glutAddMenuEntry("Depth data", DEPTH);
  582.  
  583.     mainMenu = glutCreateMenu(mainMenuFunc);
  584.     glutAddSubMenu("Visible buffer", bufferMenu);
  585.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  586.     init();
  587.     glutMainLoop();
  588.  
  589.     return 0;
  590. }
  591.